﻿using System;
using System.Collections.Generic;
using UnityEngine;

public enum EAnimator
{
    ANIMATOR_START = 75000,
    ANIMATOR_END = 80000,
}

public enum ELoopState
{
    emLoopNull = 0,
    emLoopOne = 1,
    emLoopTimes = 2,
    emLoopLoop = 3,
}

public class AnimationInfo
{
    public string animation;
    public float value;
}

//（可以传模板id过来  读取模板对应的动作 类型 次数等）
public class AnimatorCtr : MonoBehaviour
{
    List<AnimationInfo> parameterList = new List<AnimationInfo>();
    protected ELoopState mLoop = ELoopState.emLoopNull;
    protected Action<string, float, bool> mCallBack;

    protected string mCurAnimator;                      //动画状态
    protected string mLastAnimator;                     //动画状态
    public Animator mAnimator;                          //动画

    protected float mLoopTimes = 1;
    protected bool mForce = false;
    private float forceEndTime;
    private string aninatorName;

    public virtual void Update()
    {
        if (mAnimator == null) { return; }
        AnimatorStateInfo state = mAnimator.GetCurrentAnimatorStateInfo(0);
        if (!mLastAnimator.Equals(mCurAnimator))
        {
            aninatorName = "Base Layer.";
            aninatorName += mCurAnimator;
            mLastAnimator = string.Copy(mCurAnimator);
        }
        if (mLoop != ELoopState.emLoopLoop)
        {
            if (state.IsName(aninatorName) && state.normalizedTime > (mLoopTimes - 0.3f))
            {
                forceEndTime = 0;
                StopPlayerAnimator(mCurAnimator, true);
            }
        }
    }

    public void SetParaValue(string para, int value)
    {
        mAnimator.SetFloat(para, value);
    }

    public void SetAllParameterZero(string animation)
    {
        if (!IsCanUse()) { return; }
        for (int i = 0; i < parameterList.Count; ++i)
        {
            if (animation == parameterList[i].animation)
            {
                continue;
            }

            mAnimator.SetFloat(parameterList[i].animation, 0f);
            parameterList[i].value = 0;
            if (mCallBack != null)
            {
                mCallBack(parameterList[i].animation, mLoopTimes, false);
            }
        }
    }

    public void PlayAnimatorCrossFade(string animator)
    {
        if (IsCanUse())
        {
            mAnimator.CrossFade(animator, 0.2f, 0, 0);
        }
    }

    public void PlayPlayerAnimator(string animator, ELoopState eLoop, float fArg,
        float nTimes = 0, bool bForce = false, bool bFade = true, bool bAvitas = false)
    {
        if (forceEndTime > Time.time) { return; }
        if (bForce)
        {
            forceEndTime = Time.time + 1.5f;
        }

        if (string.IsNullOrEmpty(animator)
            || !IsCanUse(bAvitas))
        {
            return;
        }

        if (eLoop == ELoopState.emLoopLoop &&
            mLoop == ELoopState.emLoopOne &&
            mLoop == ELoopState.emLoopTimes)
        {
            return;
        }

        CheckAndInsertParameter(animator);
        if (eLoop == ELoopState.emLoopLoop)
        {
            if (IsCanUse())
            {
                mAnimator.SetFloat(animator, fArg, 0.3f, Time.deltaTime);
            }
        }
        else
        {
            SetAllParameterZero(animator);
            mAnimator.SetFloat(animator, fArg);
            if (bFade)
            {
                PlayAnimatorCrossFade(animator);
            }
            mLoopTimes = nTimes;
        }

        mForce = bForce;
        mLoop = eLoop;
        mCurAnimator = animator;
    }

    public void StopPlayerAnimator(string animator, bool bEnd = false, bool bAvitas = false)
    {
        if (string.IsNullOrEmpty(animator) ||
            (mForce && !bEnd) || !IsCanUse(bAvitas))
        {
            return;
        }

        mAnimator.SetFloat(animator, 0f);
        mLoop = ELoopState.emLoopNull;

        if (mCallBack != null)
        {
            mCallBack(animator, mLoopTimes, false);
        }

        if (animator == mCurAnimator && bEnd)
        {
            mForce = false;
            mCurAnimator = "";
            mLoopTimes = 1;
        }
    }

    void CheckAndInsertParameter(string animator)
    {
        bool bFind = false;
        for (int i = 0; i < parameterList.Count; ++i)
        {
            if (parameterList[i].animation == animator)
            {
                bFind = true;
                break;
            }
        }

        if (!bFind)
        {
            AnimationInfo info = new AnimationInfo();
            info.animation = animator;
            info.value = 1;
            parameterList.Add(info);
        }
    }

    bool IsCanUse(bool bAvitas = false)
    {
        if (!gameObject.activeSelf || mAnimator == null || mAnimator.runtimeAnimatorController == null
            || (!bAvitas && (mAnimator.avatar == null || !mAnimator.avatar.isValid)))
        {
            return false;
        }
        return true;
    }

    public static bool IsValidAnimatorId(int nId)
    {
        return nId >= (int)EAnimator.ANIMATOR_START && nId <= (int)EAnimator.ANIMATOR_END;
    }
}